require 'libxml'
require 'scufl/model'
require 'scufl/parser'
require 'scufl/dot'
require 't2flow/model'
require 't2flow/parser'
require 't2flow/dot'

module Tools
  def Tools.get_system_user
    User.create(:name => "Shims Library", :email => "shims-library@googlegroups.com", 
        :password => "def_pass", :access => 1) if User.find(:all, :conditions => { 
        :name => "Shims Library" }).size.zero?
    
    return User.find(:all, :conditions => { :name => "Shims Library" }).first
  end
  
  def Tools.get_model(file_content)
    xml_reader = LibXML::XML::Reader.string(file_content)
    xml_reader.read
    
    case xml_reader.name
    when /workflow/i: model = T2Flow::Parser.new.parse(file_content)
    when /scufl/i: model = Scufl::Parser.new.parse(file_content)
    else raise ""
    end
    
    xml_reader.close unless xml_reader.nil?
    
    return model
  end
  
  def Tools.create_default_categories
    AnnotationAttribute.create(
        :name => "category") unless AnnotationAttribute.find_by_name("category")
    cats = %w{List IO Metadata XML NCBI Net Text BioJava JDBC Base64 Moby}
    return_cats = []
    cats.each { |cat| 
      temp = Category.create(:name => cat)
      return_cats << (temp.nil? ? Category.find_by_name(cat) : temp)
    }
    return return_cats
  end
  
  def Tools.create_objects(user_adding, processor, model, flow_uri)
    begin
      # TRY CREATE OBJECTS
      if processor.type =~ /beanshell|local/i
        @blob_obj = ShimBlob.new(:data => processor.script)
        @blob_obj.save!
        
        @shim_obj = Shim.new(:name => processor.name, :shim_class => "Generic", 
            :user_id => user_adding.id, :shim_type => processor.type=~/local/i ? 
                "Taverna Local Worker":"Beanshell",
            :shim_blob_id => @blob_obj.id, :content_type => "text/plain", 
            :filename => "#{processor.name}.bsh", :shim_class => "Generic")
        @shim_obj.save!
      end

      if @shim_obj # OBJECT WAS SUCCESSFULLY CREATED
        processor.inputs.each { |input|
          @shim_obj.shim_inputs << ShimInput.new(:shim_id => @shim_obj.id, :name => input)
        } if processor.inputs
        
        processor.outputs.each { |output| 
          @shim_obj.shim_outputs << ShimOutput.new(:shim_id => @shim_obj.id, :name => output)
        } if processor.outputs
        
        if model.dependencies
          desc = "This beanshell may be dependant on the following files:<br/>"
          model.dependencies.each { |x| desc << "  => #{x}<br/>" }
          desc << "<br/>Please contact the owner of the workflow containing this beanshell for more information."
          if flow_uri
            desc << "<hr/><a href=#{flow_uri}> #{flow_uri} </a>"
          else
            desc << "<hr/><a href='/users/#{user_adding.id}'> #{user_adding.name} </a>"
          end
          system_user = Tools.get_system_user
          @shim_obj.create_annotations({"description" => desc}, system_user)
        end
        
        @shim_obj.create_annotations({"example_workflow" => flow_uri}, user_adding) if flow_uri
        
        shim_tags = []
        shim_cats = []
        case @shim_obj.name
          # GET TAGS
          when /genbank/i : shim_tags << "genbank"
          when /translat/i : shim_tags << "translator"
          when /filter/i : shim_tags << "filter"
          when /map/i : shim_tags << "mapper"
          when /dereferenc/i : shim_tags << "dereferencer"
          when /dna/i : shim_tags << "dna sequence"
          when /protein/i : shim_tags << "protein"
          when /parse/i : shim_tags << "parser"
          when /iterat/i : shim_tags << "iterator"
          when /affy/i : shim_tags << "affymetrix"
          when /yeast/i : shim_tags << "yeast"
          when /concat/i : shim_tags << "concatenator"
          when /xtract/i : shim_tags << "extractor"
          
          # GET CATEGORIES
          when /moby/i : shim_cats << "Moby"
          when /base64/i : shim_cats << "Base64"
          when /jdbc|sql/i : shim_cats << "JDBC"
          when /xml|xpath|xslt/i : shim_cats << "XML"
          when /dna|embl|prot|blast|bank|gene/i : shim_cats << "BioJava"
          when /string|regex|concat|byte/i : shim_cats << "Text"
          when /mail|web|uri|url|server/i : shim_cats << "Net"
          when /list|flatten|duplicate/i : shim_cats << "List"
          when /(create|read|write|concat).*file/i : shim_cats << "IO"
          when /lsid/i : shim_cats << "Metadata"
          when /snp|nucleo|protein|gene|pubmed|entrez|omin/i : shim_cats << "NCBI"
        end
        
        # GET MORE TAGS
        if processor.description
          case processor.description
            when /genbank/i : shim_tags << "genbank"
            when /translat/i : shim_tags << "translator"
            when /filter/i : shim_tags << "filter"
            when /map/i : shim_tags << "mapper"
            when /dereferenc/i : shim_tags << "dereferencer"
            when /dna/i : shim_tags << "dna sequence"
            when /protein/i : shim_tags << "protein"
            when /parse/i : shim_tags << "parser"
            when /iterat/i : shim_tags << "iterator"
            when /affy/i : shim_tags << "affymetrix"
            when /yeast/i : shim_tags << "yeast"
            when /concat/i : shim_tags << "concatenator"
            when /xtract/i : shim_tags << "extractor"
          end 
        end
        
        shim_tags.uniq!
        shim_tags.each { |tag| @shim_obj.create_annotations({"tag" => tag}, user_adding) }
          
        @shim_obj.create_annotations({"description" => processor.description},
            user_adding) if processor.description

        shim_cats.each { |cat|
          x = Annotation.new(:source_type => "User", :source_id => user_adding.id,
              :annotatable_type => "Shim", :annotatable_id => @shim_obj.id,
              :value_type => "String", 
              :attribute_id => AnnotationAttribute.find_by_name("category").id,
              :value => Category.find_by_name(cat).id)
          x.save!
        }
        
        return true
      else
        @shim_obj.destroy if @shim_obj
        @blob_obj.destroy if @blob_obj
        return false
      end
    rescue Exception => ex
      @shim_obj.destroy if @shim_obj
      @blob_obj.destroy if @blob_obj
#      puts "/* ************************************************************************* */"
#      puts "Exception: #{ex.class.name} - #{ex.message}"
#      puts ex.backtrace
#      puts "/* ************************************************************************* */"   
#      raise ex.message
      
      return false
    end
    
  end
end